<template>
  <div>
    <el-button @click="add">
      add
    </el-button>
    <el-button @click="get">
      get
    </el-button>
    <div class="code-mirror-wrappers">
      <textarea ref="textarea" />
    </div>
  </div>
</template>
<script>
// 核心文件
import CodeMirror from 'codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/addon/hint/show-hint'
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/addon/selection/active-line'
import 'codemirror/theme/idea.css'

CodeMirror.defineMode("zzzz", function (config, parserConfig) {
  let jsonldMode = parserConfig.jsonld

  function parseWords(str) {
    let obj = {},
      words = str.split(" ")
    for (let i = 0; i < words.length; ++i) obj[words[i]] = true
    return obj
  }

  // 关键字
  let keywords = parseWords("SUM  COUNT")

  let type, content

  function ret(tp, style, cont) {
    type = tp
    content = cont
    return style
  }

  function tokenBase(stream, state) {
    state.beforeParams = false
    let ch = stream.next()
    if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
      return ret("number", "number")
    } else if (ch == '[') {
      stream.skipTo(']')
      stream.eat(']')
      return ret("string", "string")
    } else if (/\d/.test(ch)) {
      stream.eatWhile(/[\w\.]/)
      return "number"
    } else if (/^[\+\-\*/]?/.test(ch)) {
      return "operator"
    } else {
      stream.eatWhile(/[\w\$_{}\xa1-\uffff]/)
      let word = stream.current()
      if (keywords && keywords.propertyIsEnumerable(word)) {
        state.beforeParams = true
        return "keyword"
      }
      return null
    }
  }

  return {
    startState: function () {
      return {
        tokenize: tokenBase,
        beforeParams: false,
        inParams: false
      }
    },
    token: function (stream, state) {
      if (stream.eatSpace()) return null
      return state.tokenize(stream, state)
    }
  }

})
// 自动补全提示
CodeMirror.registerHelper("hint", "zzzz", function (cm) {

  let hintList = ['s', 'ss', 'sss']

  let cur = cm.getCursor(),
    token = cm.getTokenAt(cur)
  let start = token.start,
    end = cur.ch
  let str = token.string

  let list = hintList.filter(function (item) {
    return item.indexOf(str) === 0
  })

  if (list.length) return {
    list: list,
    from: CodeMirror.Pos(cur.line, start),
    to: CodeMirror.Pos(cur.line, end)
  }
})

CodeMirror.defineMIME("text/x-zzzz", "zzzz")


export default {
  name: 'CodeMirrorTest',
  props: {
    json: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      codemirrorEditor: null
    }
  },
  watch: {
    json(val) {
      const editorValue = this.codemirrorEditor.getValue()
      if (val !== editorValue) {
        this.codemirrorEditor.setValue(this.json)
      }
    }
  },
  mounted() {
    this.codemirrorEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
      theme: 'idea',
      extraKeys: {"Alt-/": "autocomplete"},
      lineNumbers: true,
      matchBrackets: true,
      mode: "text/x-zzzz"
    })
    this.codemirrorEditor.setValue("1212#{aaa}#{aaa}1212\n212#{aaa}#{aaa}1212 ")
    let cursor = {line: 0, ch: 0}
    this.codemirrorEditor.eachLine((line) => {
      for (let i = 0; i < line.text.length; i++) {
        if (line.text.charAt(i) === '#' && line.text.charAt(i + 1) === '{') {
          console.log(i)
          cursor.ch = i
          let htmlNode = document.createElement("span")
          htmlNode.innerText = "单行文本"
          htmlNode.className = 'cm-field-value'
          this.codemirrorEditor.markText(cursor, {line: cursor.line, ch: cursor.ch + 6}, {
            className: 'cm-field-value',
            replacedWith: htmlNode
          })
        }
      }
      cursor.line++
    })
    this.codemirrorEditor.on('change', (cm) => {
      this.$emit('change', cm.getValue())
    })
    this.codemirrorEditor.on("inputRead", () => {
      this.codemirrorEditor.showHint()
    })

  },
  methods: {
    add() {
      // create a node
      let htmlNode = document.createElement("span")
      htmlNode.innerText = "单行文本"
      htmlNode.className = 'cm-field-value'
      let cursor = this.codemirrorEditor.getCursor()
      console.log(cursor)
      this.codemirrorEditor.replaceRange("#{aaa}", cursor, cursor)
      // call this after you initialized the editor.
      // the position must be like this {ch: YourCharecterNumber, line: YourLineNumber}
      //   this.codemirrorEditor.addLineWidget(1, htmlNode, true)
      this.codemirrorEditor.markText(cursor, {line: cursor.line, ch: cursor.ch + 6}, {
        className: 'cm-field-value',
        replacedWith: htmlNode
      })
    },
    get() {
      this.codemirrorEditor.eachLine((line) => {
        console.log(line)
      })
      console.log(this.codemirrorEditor.getValue())
    },
    refresh() {
      /*
       * refresh: Fires when the editor is refreshed or resized.
       * Mostly useful to invalidate cached values that depend on the editor or character size.
       */
      this.codemirrorEditor && this.codemirrorEditor.refresh()
    }
  }
}
</script>
<style>
.cm-field-value {
  background: #EBF5FF;
  color: #008DCD;
}
</style>
